/*************
 * 检测基类
 *
 */
package com.yy.ttmodule.cardStatus;

import android.content.Context;
import android.net.LocalSocket;
import android.net.LocalSocketAddress;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.ByteBuffer;

import android.util.Log;

/**
 * Created by wujun on 17-8-31.
 */

public class BmChecker extends Thread {

    //注意下面的与服务端相关，不能单独修改
    private static final String BM_SOCKET = "com.dtt.bmserver";
    private static final int ID_GET_BM_CARD_STATE = 0x1000;
    private static final int ID_GET_BM_BAR_STATE = 0x1001;

    public static final int ID_DESTROY_KEY = 0x1002;         //毁钥
    public static final int ID_SWITCH_BM_CHANNEL = 0x1003;   //切换BM(保密)通道

    public static final int ID_SET_BM_CARD_STATE = 0x1010;   //保密卡模式设置(54)
    public static final int ID_GET_BM_CARD_POWER_ON_STATE = 0x1011;  //上电查询(54)

    private static final String TAG = "BmChecker";

    private Context mContext;
    private LocalSocket mSocket = new LocalSocket();
    private StatusBean mStatusBean;
    private int mId;
    private volatile boolean mStoped = false;

    /**
     * @param context
     * @param statusBean
     */
    public BmChecker(Context context, StatusBean statusBean) {
        this.mContext = context;
        this.mStatusBean = statusBean;
        updateId();
    }

    /**
     * 
     */
    private void updateId() {
        if (StatusBean.TYPE_CF_CARD == mStatusBean.getType()) {
            mId = ID_GET_BM_CARD_STATE;
        } else if (StatusBean.TYPE_BM_BAR == mStatusBean.getType()) {
            mId = ID_GET_BM_BAR_STATE;
        } else if (StatusBean.TYPE_CF_MODE == mStatusBean.getType()) {
            mId = ID_SET_BM_CARD_STATE;
        } else if (StatusBean.TYPE_CF_POWER_ON == mStatusBean.getType()) {
            mId = ID_GET_BM_CARD_POWER_ON_STATE;
        } else {
            //TODO
            assert false;
        }
    }

    /**
     * @param stop
     */
    public void setStoped(boolean stop) {
	    mStoped = stop;
    }

    @Override
    public void run() {
        super.run();

        try {
            mSocket.connect(new LocalSocketAddress(BM_SOCKET));

            int msgLength = 4;
            ByteBuffer buffer = ByteBuffer.allocate(8);
            buffer.putInt(msgLength);
            buffer.putInt(mId);

            boolean beOk = false;
            final int interval = 3;

            do {
                if (mStoped) {
                    break;
                }
                Log.i(TAG, "checkStatus this.mStatusBean = " + this.mStatusBean);
                beOk = checkStatus(mSocket, buffer.array());
                if (!beOk) {
                    try {
                        Thread.sleep(interval * 1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            } while (!beOk);

            if (beOk) {
                mStatusBean.setStatus(StatusBean.STATUS_OK);
            }

        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
	        Log.i(TAG, "e =" + e);
        } finally {
            if (null != mSocket) {
                try {
                    mSocket.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * @param socket
     * @param buf
     * @return
     */
    private boolean checkStatus(LocalSocket socket, byte[] buf) {
        boolean writeResult = writeBmCommandToServer(mSocket, buf);
        if (writeResult) {
            int readResult = readBmResponse(mSocket);
            if (readResult > 0) {
                return true;
            }
        }
        return false;
    }

    /**
     * @param socket
     * @param buf
     * @return
     */
    private boolean writeBmCommandToServer(LocalSocket socket, byte[] buf) {
        if ((socket == null) || (buf == null)) {
            return false;
        }
        try {
            OutputStream os = socket.getOutputStream();
            os.write(buf);
            os.flush();
        } catch (IOException e) {
            e.printStackTrace();
            Log.e(TAG, "writeBmCommandToServer IOException");
            return false;
        }
        return true;
    }

    /**
     * @param soket
     * @return
     */
    private int readBmResponse(LocalSocket soket) {
        final int MAX_LOOP_TIMES = 5;
        if (soket == null) {
            return -1;
        }
        try {
            InputStream is = soket.getInputStream();
            int count = 0;
            int loop = 0;
            while (loop < MAX_LOOP_TIMES) {
                count = is.available();
                if (count > 0) {
                    break;
                }
                Thread.sleep(1000);
                loop++;
            }
            if (loop >= MAX_LOOP_TIMES) {
                return -2;
            }
            byte[] buf = new byte[count];
            is.read(buf);
            ByteBuffer byteBuffer = ByteBuffer.wrap(buf);
            if (byteBuffer.remaining() < 4) {
                return -1;
            }
            int msgLength = byteBuffer.getInt();
            if (byteBuffer.remaining() < msgLength) {
                return -1;
            }
            int msgId = byteBuffer.getInt();
            String s = new String(byteBuffer.array(), 8, msgLength - 4);

            if (resolveBmResponse(msgId, s)) {
                return 1;
            }
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            return -1;
        }
        return 0;
    }

    /**
     * @param msgId
     * @param response
     * @return
     */
    private boolean resolveBmResponse(int msgId, String response) {
        if (null == response) {
            return false;
        }
        Log.i(TAG, "msgId = " + msgId + ",response=" + response);
        switch (msgId) {
            case ID_GET_BM_CARD_STATE: {
                if (response.contains("ERROR")) {
                    return false;
                } else if (response.equalsIgnoreCase("OK")) {
                    return true;
                }
                break;
            }
            case ID_GET_BM_BAR_STATE: {
                if (response.contains("ERROR")) {
                    return false;
                } else if (response.equalsIgnoreCase("OK")) {
                    return true;
                }
                break;
            }
        }
        return false;
    }
}
